/**
 * @file alarm.c
 * @author ait_zhengchunyu (ait_zhengchunyu@163.com)
 * @brief 
 * @version 0.1
 * @date 2022-02-07
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include "alarm.h"
#include "../dbg/dbg.h"

static struct alram_dev_t alarm_device;

/**
 * @brief 此函数为告警信息执行函数，
 * 
 * @return uint8_t 
 */
static uint8_t alarm_obj_on(struct alram_dev_t * dev,uint8_t num)
{   
    if((dev->obj[num].check())==1)
    {
       // dev->obj[num].flag = 1;    
			return 1;
    }
    return 0;

}
static uint8_t alarm_obj_delay(struct alram_dev_t * dev,uint8_t num)
{
	   if(dev->obj[num].check())
		 {
			 dev->obj[num].delay_cnt++;
			 if(dev->obj[num].delay_cnt>=dev->obj[num].delay_cnt_val)
			 {
				 dev->obj[num].delay_cnt = dev->obj[num].delay_cnt_val;
				 return 1;
			 }
		 }
		 else
		 {
			 dev->obj[num].delay_cnt = 0;
			 return 0;
		 }
    return 0;
}
static int alarm_get_state(struct alram_dev_t * dev, uint8_t num)
{
    int ret = 0;
    if(dev == NULL)
    return -1;
    if(num>=ALARM_FUCTION_NUM)
    return -2;
    if(dev->obj[num].type== 0xff)//不响应直接返回，相当于屏蔽
    {
        return 0;
    }
    switch(dev->obj[num].type)
    {
        case 0://立即响应
        ret = dev->obj_on(dev,num);
        break;
        case 1://延时响应
         ret = dev->obj_delay_on(dev,num);
        break;
        default://不相应
				ret = 0;
        break;
    }
    return ret;
}
static int alarm_clear_fault_num(struct alram_dev_t *dev)
{
   dev->fault_num = 0;
	return 0;
}
static int alarm_clear_warn_num(struct alram_dev_t *dev)
{
	dev->warn_num = 0;
	return 0;
}
static int alarm_flag_parse(struct alram_dev_t *dev,uint8_t num)
{
    int j,k;
    if(dev == NULL) return -1;
    if(num>=ALARM_FUCTION_NUM) return -2;
    j=num/8;
    if(j<0)return -3;
    k=num%8;
    if(k<0)return -4;

    switch (dev->obj[num].err_code) 
    {
        case 0://不处理 
        break;
        case 1://故障
            dev->fault_flag_buf[j]|=1<<k;
            dev->fault_num = num+1;
        break;
        case 2://警告
            dev->warn_flag_buf[j]|=1<<k;
            dev->warn_num = num+1;
        break;
        case 3://故障和警告
            dev->fault_flag_buf[j]|=1<<k;
            dev->warn_flag_buf[j] |=1<<k;
            dev->fault_num = num;
            dev->warn_num = num;
        break;
        default: 
        break;
    }   
    return 0;
}
/**
 * @brief 报警处理函数
 * 
 * @param dev 
 * @return uint8_t  0 没有告警 1 有告警
 */
int i_test, j_test,k_test;
static uint8_t alarm_loop_func(struct alram_dev_t *dev)
{

  //int i, j,k;
    for (i_test=0;i_test<ALARM_FUCTION_NUM;i_test++) 
    {
        j_test=i_test/8;
        if(j_test<0)return 0;
        k_test=i_test%8;
        if(k_test<0)return 0;
        if(dev->get_alarm(dev, i_test)==1)//异常
        {
            alarm_flag_parse(dev, i_test);
        }
        else
        {
            dev->fault_flag_buf[j_test]&=~(1<<k_test);
            dev->warn_flag_buf[j_test]&=~(1<<k_test);
        }
    }

	return 0;
}
static int alarm_set_delay(struct alram_dev_t *dev,uint8_t num,uint16_t delay)
{
    if(dev == NULL)
    return -1;
    if(num>=ALARM_FUCTION_NUM)
    return -2;
    dev->obj[num].delay_cnt_val = delay;
    dev->obj[num].delay_cnt = dev->obj[num].delay_cnt_val ;
    return 0 ;
}

/**
 * @brief 获取告警值
 * 
 * @param dev    
 * @param pflault  报警值数组  
 * @return uint8_t  报警值数组长度
 */
static uint8_t alarm_get_flault(struct alram_dev_t *dev,uint8_t *pflault)
{
    pflault = dev->fault_flag_buf;
    return FLAUT_MAX_NUM;
}
/**
 * @brief 获取警告标志
 * 
 * @param dev 
 * @param [out]  pwarn 警告标志数组  
 * @return uint8_t pwarn 数组长度 
 */
static uint8_t alarm_get_warn(struct alram_dev_t *dev,uint8_t *pwarn)
{
    pwarn = dev->warn_flag_buf;
    return WARN_MAX_NUM;
}
/**
 * @brief 初始化告警对象
 * 
 * @param dev 告警设备
 * @param obj 告警对象 
 * @param num 告警对象编号
 * @return int 
 */
static int alarm_obj_init(struct alram_dev_t *dev,struct alarm_obj_t *obj,uint8_t num)
{
    if((dev==NULL)||(obj==NULL)||(num>ALARM_FUCTION_NUM-1))
    {
        return -1;
    }
    dev->obj[num].type         =    obj->type;
    dev->obj[num].err_code     =    obj->err_code;
    dev->obj[num].delay_cnt_val=    obj->delay_cnt_val;
    dev->obj[num].delay_cnt    =    obj->delay_cnt;
    dev->obj[num].check        =    obj->check;
    return 0;
}
int alarm_init(struct alram_dev_t **dev)
{
    if(dev==NULL) 
    return -1;

    alarm_device.fault_num     = 0;
    alarm_device.warn_num     = 0;
    alarm_device.pre_faluted    = 0;
    alarm_device.obj_on      	= alarm_obj_on;
    alarm_device.obj_delay_on	= alarm_obj_delay;
    alarm_device.set_delay   	= alarm_set_delay;
    alarm_device.get_alarm   	= alarm_get_state;
    alarm_device.loop_func      = alarm_loop_func;
    alarm_device.obj_init       = alarm_obj_init;
    alarm_device.get_flault     = alarm_get_flault;
    alarm_device.clear_flaut_num=alarm_clear_fault_num;
    alarm_device.get_warn       = alarm_get_warn;
    alarm_device.clear_warn_num=alarm_clear_warn_num;
    *dev = &alarm_device;
    return 0;
}


